import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_datetime_picker_plus/flutter_datetime_picker_plus.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:omni_datetime_picker/omni_datetime_picker.dart';
import 'package:orginone/components/XDialogs/dialog_utils.dart';
import 'package:orginone/dart/extension/index.dart';
import 'package:orginone/components/XImage/XImage.dart';
import 'package:orginone/config/theme/space.dart';
import 'package:orginone/dart/base/model.dart';
import 'package:orginone/dart/base/storages/models/asset_creation_config.dart';
import 'package:orginone/dart/core/target/base/belong.dart';
import 'package:orginone/dart/core/target/base/target.dart';
import 'package:orginone/dart/core/target/innerTeam/department.dart';
import 'package:orginone/dart/core/target/team/company.dart';
import 'package:orginone/config/theme/unified_style.dart';
import 'package:orginone/main.dart';
import 'package:orginone/routers/pages.dart';

import '../XTextField/XTextField.dart';
import 'components/XRadio/XRadio.dart';
import 'components/XSelect/XSelect.dart';

typedef MappingComponentsCallback = Widget Function(
    Fields data, ITarget target);

Map<String, MappingComponentsCallback> mappingComponents = {
  "keyValueText": mappingKeyVueTextWidget,
  "text": mappingTextWidget,
  "input": mappingInputWidget,
  "select": mappingSelectBoxWidget,
  "selectTime": mappingSelectTimeBoxWidget,
  "selectTimeRange": mappingSelectTimeRangeBoxWidget,
  "selectDate": mappingSelectDateBoxWidget,
  "selectDateRange": mappingSelectDateRangeBoxWidget,
  "selectPerson": mappingSelectPersonBoxWidget,
  "selectDepartment": mappingSelectDepartmentBoxWidget,
  "selectGroup": mappingSelectGroupBoxWidget,
  "switch": mappingSwitchWidget,
  "router": mappingRouteWidget,
  "upload": mappingUploadWidget,
  "reference": mappingReferenceTextWidget,
};

MappingComponentsCallback mappingKeyVueTextWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }

  String content = "";
  if (data.defaultData.value != null) {
    if (data.defaultData.value is String) {
      content = data.defaultData.value;
    } else {
      content = data.defaultData.value?.values?.first.toString() ?? "";
    }
  } else {
    content = data.controller?.text ?? '';
  }
  // LogUtil.d('mappingKeyVueTextWidget');
  // LogUtil.d(content);
  Widget row = <Widget>[
    Text('${data.title}:  '),
    // Text(data.defaultData.value ?? data.controller?.text ?? ''),
    Text(content),
  ].toRow();

  return Container(
    margin: EdgeInsets.only(
        left: (data.marginLeft ?? 0).h,
        right: (data.marginRight ?? 0).h,
        top: (data.marginTop ?? 0).h,
        bottom: (data.marginBottom ?? 0).h),
    child: row,
  );
};
MappingComponentsCallback mappingTextWidget = (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XTextField.input(
        title: data.title,
        content: data.defaultData.value,
        required: data.required ?? false,
        enabled: !(data.readOnly ?? false),
        showLine: true,
        // textStyle: XFonts.size22Black0
      ),
    );
  });
};
MappingComponentsCallback mappingReferenceTextWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  String content = '';
  if (data.defaultData.value is String) {
    content = data.defaultData.value;
  } else {
    content = data.defaultData.value?.first['text'] ?? "";
  }
  return Container(
    margin: EdgeInsets.only(
        left: (data.marginLeft ?? 0).h,
        right: (data.marginRight ?? 0).h,
        top: (data.marginTop ?? 0).h,
        bottom: (data.marginBottom ?? 0).h),
    child: XTextField.input(
      title: data.title ?? "", content: content,
      required: data.required ?? false,
      enabled: !(data.readOnly ?? false),
      showLine: true,
      // textStyle: XFonts.size22Black0
    ),
  );
  return Obx(() {
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XTextField.input(
        title: data.title ?? "",
        content: data.defaultData.value['text'] ?? "",
        required: data.required ?? false,
        enabled: !(data.readOnly ?? false),
        showLine: true,
        // textStyle: XFonts.size22Black0
      ),
    );
  });
};
MappingComponentsCallback mappingInputWidget = (Fields data, ITarget target) {
  List<TextInputFormatter>? inputFormatters;
  if (data.regx != null) {
    inputFormatters = [
      FilteringTextInputFormatter.allow(RegExp(data.regx!)),
    ];
  }
  if (data.hidden ?? false) {
    return Container();
  }
  return Container(
    margin: EdgeInsets.only(
        left: (data.marginLeft ?? 0).h,
        right: (data.marginRight ?? 0).h,
        top: (data.marginTop ?? 0).h,
        bottom: (data.marginBottom ?? 0).h),
    child: XTextField.input(
        title: data.title,
        hint: data.hint ?? "请输入",
        maxLines: data.maxLine,
        controller: data.controller,
        onChanged: (str) {
          // data.defaultData.value = str;
        },
        required: data.required ?? false,
        // textStyle: XFonts.size22Black0,
        // inputFormatters: inputFormatters,
        enabled: !(data.readOnly ?? false),
        showLine: true),
  );
};

MappingComponentsCallback mappingSelectBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = "";
    if (data.defaultData.value != null) {
      if (data.defaultData.value is String) {
        content = data.defaultData.value;
      } else {
        content = data.defaultData.value?.values?.first.toString() ?? "";
      }
    }
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () {
          if (!(data.readOnly ?? false)) {
            PickerUtils.showListStringPicker(navigatorKey.currentState!.context,
                titles: data.select!.values.toList(), callback: (str) {
              int index = data.select!.values.toList().indexOf(str);
              dynamic key = data.select!.keys.toList()[index];
              data.defaultData.value = {key: str};
            });
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectTimeBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () {
          if (!(data.readOnly ?? false)) {
            DatePicker.showDateTimePicker(navigatorKey.currentState!.context,
                currentTime: DateTime.now(),
                locale: LocaleType.zh, onConfirm: (date) {
              data.defaultData.value = date.format(format: "yyyy-MM-dd HH:mm");
            });
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectTimeRangeBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value?.join('至') ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () async {
          if (!(data.readOnly ?? false)) {
            List<DateTime>? dateTimeList = await showOmniDateTimeRangePicker(
                context: navigatorKey.currentState!.context,
                type: OmniDateTimePickerType.dateAndTime);
            if (dateTimeList != null) {
              dateTimeList.sort((a, b) => a.compareTo(b));
              data.defaultData.value = dateTimeList
                  .map((e) => e.format(format: "yyyy-MM-dd HH:mm"))
                  .toList();
            }
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectDateBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () {
          if (!(data.readOnly ?? false)) {
            DatePicker.showDatePicker(navigatorKey.currentState!.context,
                currentTime: DateTime.now(),
                locale: LocaleType.zh, onConfirm: (date) {
              data.defaultData.value = date.format(format: "yyyy-MM-dd");
            });
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectDateRangeBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value?.join('至') ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () async {
          if (!(data.readOnly ?? false)) {
            List<DateTime>? dateTimeList = await showOmniDateTimeRangePicker(
                context: navigatorKey.currentState!.context,
                type: OmniDateTimePickerType.date);
            if (dateTimeList != null) {
              dateTimeList.sort((a, b) => a.compareTo(b));
              data.defaultData.value = dateTimeList
                  .map((e) => e.format(format: "yyyy-MM-dd"))
                  .toList();
            }
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectPersonBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value?.name ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () {
          if (!(data.readOnly ?? false)) {
            var users = target.members;
            PickerUtils.showListStringPicker(navigatorKey.currentState!.context,
                titles: users.map((e) => e.name).toList(), callback: (str) {
              data.defaultData.value =
                  users.firstWhere((element) => element.name == str);
            });
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectDepartmentBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value?.name ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () {
          if (!(data.readOnly ?? false)) {
            List<ITarget> loadDepartments(List<IDepartment> departments) {
              List<ITarget> team = [];

              for (var value in departments) {
                team.add(value);
                if (value.children.isNotEmpty) {
                  team.addAll(loadDepartments(value.children));
                }
              }
              return team;
            }

            List<ITarget> team =
                loadDepartments((target as Company).departments);
            PickerUtils.showListStringPicker(navigatorKey.currentState!.context,
                titles: team.map((e) => e.metadata.name).toList(),
                callback: (str) {
              data.defaultData.value = team
                  .firstWhere((element) => element.metadata.name == str)
                  .metadata;
            });
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingSelectGroupBoxWidget =
    (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String content = '';
    content = data.defaultData.value?.name ?? "";
    return Container(
      margin: EdgeInsets.only(
          left: (data.marginLeft ?? 0).h,
          right: (data.marginRight ?? 0).h,
          top: (data.marginTop ?? 0).h,
          bottom: (data.marginBottom ?? 0).h),
      child: XSelect.dialog(
        data.title ?? "",
        content,
        onTap: () {
          if (!(data.readOnly ?? false)) {
            List<ITarget> parentTarget = (target as IBelong).parentTarget;
            PickerUtils.showListStringPicker(navigatorKey.currentState!.context,
                titles: parentTarget.map((e) => e.metadata.name).toList(),
                callback: (str) {
              data.defaultData.value = parentTarget
                  .firstWhere((element) => element.metadata.name == str)
                  .metadata;
            });
          }
        },
        showLine: true,
        required: data.required ?? false,
        textStyle: XFonts.size22Black0,
      ),
    );
  });
};

MappingComponentsCallback mappingRouteWidget = (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    return XSelect.dialog(data.title ?? "", data.defaultData.value?.name ?? "",
        required: data.required ?? false, onTap: () {
      if (!(data.readOnly ?? false)) {
        RoutePages.to(path: data.router!);
      }
    }, showLine: true);
  });
};

MappingComponentsCallback mappingSwitchWidget = (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  if (data.select!.isEmpty) {
    return mappingTextWidget(data, target);
  }
  return Stack(
    children: [
      Container(
        color: Colors.white,
        width: double.infinity,
        padding: EdgeInsets.symmetric(vertical: 10.h, horizontal: 16.w),
        child: Container(
          decoration: BoxDecoration(
              color: Colors.white,
              border: Border(
                  bottom: BorderSide(color: Colors.grey.shade200, width: 0.5))),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                data.title ?? '',
                style: XFonts.size22Black0,
              ),
              data.select!.isEmpty
                  ? const SizedBox()
                  : Obx(() {
                      List<Widget> children = [];
                      data.select?.forEach((key, value) {
                        children.add(XRadio.text(value, key,
                            groupValue: data.defaultData.value,
                            onChanged: (dynamic v) {
                          if (!(data.readOnly ?? false)) {
                            data.defaultData.value = v;
                          }
                        }, padding: EdgeInsets.symmetric(vertical: 5.h)));
                      });

                      return Row(children: children);
                    }),
            ],
          ),
        ),
      ),
      Positioned(
        top: 5.h,
        left: 10.w,
        child: (data.required ?? false)
            ? const Text(
                "*",
                style: TextStyle(color: Colors.red),
              )
            : Container(),
      )
    ],
  );
};

MappingComponentsCallback mappingUploadWidget = (Fields data, ITarget target) {
  if (data.hidden ?? false) {
    return Container();
  }
  return Obx(() {
    String str = '';

    var json;
    List<FileItemShare> files;

    if (data.defaultData.value != null) {
      if (data.defaultData.value is String) {
        str = data.defaultData.value;
        json = jsonDecode(str);
        if (json is List && json.isNotEmpty) {
          files = json.map((e) => FileItemShare.fromJson(e)).toList();
          return <Widget>[
            Text(
              '${data.title}',
            ),
            Wrap(
              children: files
                  .map((e) => Row(
                        children: [
                          XImage.entityIcon(
                            e,
                            width: 35,
                            circular: false,
                          ),
                          Text(
                            '${e.name}',
                            style: const TextStyle(color: XColors.blue),
                          )
                        ],
                      ).onTap(() => RoutePages.jumpFile(file: e)))
                  .toList(),
            ).paddingVertical(AppSpace.button)
          ]
              .toColumn(crossAxisAlignment: CrossAxisAlignment.start)
              .border(bottom: 0.5, color: Colors.grey.shade200)
              .marginSymmetric(horizontal: AppSpace.page.w);
        } else {
          return Container();
        }
      }
    }
    return Container();
    // return XSelect.dialog(
    //   data.title ?? "",
    //   str,
    //   required: data.required ?? false,
    //   onTap: () async {
    //     if (!(data.readOnly ?? false)) {
    //       FilePickerResult? result =
    //           await FilePicker.platform.pickFiles(type: FileType.any);
    //       if (result != null) {
    //         LoadingDialog.showLoading(navigatorKey.currentState!.context);
    //         var docDir = target.directory;
    //         PlatformFile file = result.files.first;
    //         var file1 = File(file.path!);
    //         var item = await docDir.createFile(file1);
    //         if (item != null) {
    //           data.defaultData.value = item.shareInfo();
    //         }
    //         LoadingDialog.dismiss(navigatorKey.currentState!.context);
    //       }
    //     }
    //   },
    //   showLine: true,
    //   textStyle: XFonts.size22Black0,
    // );
  });
};
